// 闭包的作用：
// 1. 封装变量：闭包可以帮助把一些不需要暴露在全局的变量封装成“私有变量”

var mult = function () {
    var a = 1;

    for (var i = 0, l = arguments.length; i < l; i++) {
        a = a * arguments[i];
    }
    return a;
};

// 加入缓存机制提高性能
var cache = {};

var mult = function () {
    var args = Array.prototype.join.call(arguments, ',');
    console.log(args);
    
    if (cache[args]) {
        return cache[args];
    }

    var a = 1;

    for (var i = 0, l = arguments.length; i < l; i++) {
        a = a * arguments[i];
    }

    return cache[args] = a;
}

mult(1,2,3);

// cache 变量封闭在 mult 函数内部，这样可以减少页面中的全局变量，以避免这个变量在其他地方被不小心修改而引发错误。
var mult = (function () {
    var cache = {};
    
    return function () {
        var args = Array.prototype.join.call(arguments, ',');
        console.log(args);
        console.log(cache);

        if (args in cache) {
            return cache[args];
        }

        var a = 1;
        for( var i = 0, l = arguments.length; i < l; i++) {
            a = a * arguments[i];
        }

        return cache[args] = a;
    }
})();

// 提炼函数：如果在一个大函数中有一些代码块能够独立出来，我们常常把这些代码块封装在独立的小函数里。
// 独立出来的小函数有助于代码复用,如果这些小函数有一个良好的命名, 它们本身也起到了注释的作用.
// 如果这些小函数不需要在程序的其他地方使用,最好是把它们用闭包封闭起来.
var mult = (function () {
    var cache = {};
    // 封闭 calculate 函数
    var calculate = function () {
        var a = 1;
        for (var i = 0, l = arguments.length; i < l; i++) {
            a = a * arguments[i];
        }
        return a;
    };

    return function () {
        var args = Array.prototype.join.call(arguments, ',');

        if (args in cache) {
            return cache[args];
        }

        return cache[args] = calculate.apply(null, arguments);
    }
})();